package current;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class ProducerCustomerModel {
    final static int MAX = 10;

    LinkedList<Integer> queue = new LinkedList<>();

    int readData() throws InterruptedException {
        // 模拟运算成本，需要消耗一定时间
        TimeUnit.MICROSECONDS.sleep((long) (Math.random() * 1000));
        return (int) Math.floor(Math.random());
    }

    // 生产者
    public void readDb() throws InterruptedException {
        synchronized (queue) {
            if (queue.size() == MAX) {
                queue.wait();
                return;
            }
            int data = readData();
            if (queue.size() == 1) {
                // 单纯的notify会造成死锁，使用notifyAll可以解决死锁，但不应该总是notifyAll
                queue.notifyAll();
            }
            queue.add(data);
        }
    }

    // 消费者
    public void calculate() throws InterruptedException {
        synchronized (queue) {
            if (queue.size() == 0) {
                queue.wait();
                return;
            }
            Integer data = queue.remove();
            if (queue.size() == MAX - 1) {
                // 单纯的notify会造成死锁，使用notifyAll可以解决死锁，但不应该总是notifyAll
                queue.notifyAll();
            }
            System.out.println("queue-size: " + queue.size());
            data *= 100;
        }
    }

    public static void main(String[] args) {
        ProducerCustomerModel model = new ProducerCustomerModel();
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                while (true) {
                    try {
                        model.readDb();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        new Thread(() -> {
            while (true) {
                try {
                    model.calculate();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

}
